package com.matt.sooncleaner.arch

import android.view.LayoutInflater
import android.view.ViewGroup
import androidx.viewbinding.ViewBinding
import java.io.InvalidClassException
import java.lang.reflect.Method
import java.lang.reflect.ParameterizedType

fun <T> Class<T>.getInflateMethod(): Method? {
    return this.getMethod(
        "inflate",
        LayoutInflater::class.java,
        ViewGroup::class.java,
        Boolean::class.java
    ).apply {
        isAccessible = true
    }
}

fun <T: ViewBinding> ViewGroup.inflateBinding(clazz: Class<T>): T {
    val layoutInflater = LayoutInflater.from(context)
    val inflateMethod =
        clazz.getInflateMethod() ?: throw NullPointerException("cannot inflate method")
    try {
        return inflateMethod.invoke(null, layoutInflater, this, false) as T
    } catch (e: Exception) {
        throw e
    }
}

fun <VB : ViewBinding> getViewBindingClass(component: Any): Class<VB> {
    val componentClass = component.javaClass
    if (componentClass.genericSuperclass !is ParameterizedType) {
        return getViewBindingClass<VB>(componentClass.superclass!!)
    }
    val generics = (componentClass.genericSuperclass as ParameterizedType).actualTypeArguments
    if (generics.isEmpty() || !(generics[0] as Class<VB>).simpleName.endsWith("Binding")) {
        if (componentClass.superclass == null) {
            throw InvalidClassException("The first generic type a class must be ViewBinding")
        } else {
            return getViewBindingClass<VB>(componentClass.superclass!!)
        }
    }
    return generics[0] as Class<VB>
}
